<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>JS在线图片压缩</title>
		<style type="text/css">
			.box {
				width: 100%;
				height: 100%;
			}

			.title {
				text-align: center;
				border-bottom: 1px solid #666666;
				padding: 10px 0 16px;
			}

			.containor {
				width: 1000px;
				margin: 0 auto;
			}

			.img_box {
				width: 100%;
				max-height: 700px;
				margin-top: 30px;
			}

			.img_box img {
				width: 100%;
				height: 100%;
				border-radius: 2px;
			}

			.info span {
				padding-right: 24px;
			}

			.btn {
				border: 0;
				background: #409eff;
				color: #fff;
				padding: 6px 15px;
				cursor: pointer;
				border-radius: 2px;
				margin: 0;
			}

			.btn:hover {
				box-shadow: 0 0 8px 0 rgb(232 237 250 / 60%), 0 2px 4px 0 rgb(232 237 250 / 50%);
				opacity: .8;
			}

			.btn:focus {
				outline: none;
			}

			#down {
				cursor: pointer;
				display: none;
			}
			
			.down_btn {
				margin-top: 10px;
				display: flex;
				flex-direction: row-reverse;
			}
		</style>
	</head>
	<body>

		<div class="box">
			<h2 class="title">图片在线压缩</h2>
			<div class="containor">
				<div class="item">
					<span class="tit">选择图片：</span>
					<input type="file" id="inputimg">
					<button class="btn" id="compression">压缩</button>

					<div class="img_box">
						<p class="info">
							<span id="com_before"></span>
							<span id="com_after"></span>
							<span id="com_ratio"></span>
						</p>
						<img id="img_">
						<div class="down_btn">
							<button class="btn" id="down">下载</button>
						</div>

					</div>
				</div>
			</div>
		</div>
		<script type="text/javascript">
			window.onload = function() {

				let file_name = null
				let resFile = null

				fimgclick = function(e) {
					//获取文件
					let self = this;
					let resultFile = e.target.files[0];
					if (resultFile) {
						let reader = new FileReader();
						let data = "";
						reader.readAsDataURL(resultFile);
						// 读取成功后的回调
						reader.onloadend = function() {
							let urlData = this.result;
							let img = new Image();
							img.src = urlData;
							img.onload = function() {
								//  此处调用 lessCompress 方法 传入 img 对象
								self.imgData = self.lessCompress(img);

								console.log("self.imgData", self.imgData);

								document.getElementById('img_').src = self.imgData

								document.getElementById('down').href = self.imgData
								data = self
									.lessCompress(img)
									.replace("data:image/jpeg;base64,", "");

							}
						}
					}
				};

				// 下载
				document.getElementById('down').addEventListener("click", function() {
					var link = document.createElement('a');

					link.download = file_name

					link.href = resFile;

					link.click()
				})

				// 压缩
				document.getElementById('compression').addEventListener('click', function() {
					let resultFile = document.getElementById('inputimg').files[0]
					
					if(!resultFile){
						alert('请上传文件！')
						return false
					}

					file_name = document.getElementById('inputimg').files[0].name


					if (resultFile) {
						let reader = new FileReader();
						let data = "";
						reader.readAsDataURL(resultFile);
						// 读取成功后的回调
						reader.onloadend = function() {
							let urlData = this.result;
							let img = new Image();
							img.src = urlData;
							img.onload = function() {
								//  此处调用 lessCompress 方法 传入 img 对象
								self.imgData = self.lessCompress(img);

								resFile = self.imgData

								document.getElementById('img_').src = self.imgData
								
								document.getElementById('down').style.display = 'block'
								data = self
									.lessCompress(img)
									.replace("data:image/jpeg;base64,", "");

							}
						}
					}
				});

				// 更小的压缩图片
				lessCompress = function(img, Orientation) {
					let canvas = document.createElement("canvas");
					let ctx = canvas.getContext("2d");
					//瓦片canvas
					let tCanvas = document.createElement("canvas");
					let tctx = tCanvas.getContext("2d");
					let initSize = img.src.length;
					let width = img.width;
					let height = img.height;
					//如果图片大于四百万像素，计算压缩比并将大小压至400万以下
					let ratio;
					if ((ratio = (width * height) / 4000000) > 1) {
						// console.log("大于400万像素");
						ratio = Math.sqrt(ratio);
						width /= ratio;
						height /= ratio;
					} else {
						ratio = 1;
					}
					canvas.width = width;
					canvas.height = height;
					//         铺底色
					ctx.fillStyle = "#fff";
					ctx.fillRect(0, 0, canvas.width, canvas.height);
					//如果图片像素大于100万则使用瓦片绘制
					let count;
					if ((count = (width * height) / 1000000) > 1) {
						// console.log("超过100W像素");
						count = ~~(Math.sqrt(count) + 1); //计算要分成多少块瓦片
						//            计算每块瓦片的宽和高
						let nw = ~~(width / count);
						let nh = ~~(height / count);
						tCanvas.width = nw;
						tCanvas.height = nh;
						for (let i = 0; i < count; i++) {
							for (let j = 0; j < count; j++) {
								tctx.drawImage(
									img,
									i * nw * ratio,
									j * nh * ratio,
									nw * ratio,
									nh * ratio,
									0,
									0,
									nw,
									nh
								);
								ctx.drawImage(tCanvas, i * nw, j * nh, nw, nh);
							}
						}
					} else {
						ctx.drawImage(img, 0, 0, width, height);
					}
					//修复ios上传图片的时候 被旋转的问题
					if (Orientation != "" && Orientation != 1) {
						switch (Orientation) {
							case 6: //需要顺时针（向左）90度旋转
								this.rotateImg(img, "left", canvas);
								break;
							case 8: //需要逆时针（向右）90度旋转
								this.rotateImg(img, "right", canvas);
								break;
							case 3: //需要180度旋转
								this.rotateImg(img, "right", canvas); //转两次
								this.rotateImg(img, "right", canvas);
								break;
						}
					}
					// 进行最小压缩
					// 第二个参数0.1-1 0.1是最小很影响图片清晰度
					let ndata = canvas.toDataURL("image/jpeg", 0.5);

					// console.log("压缩前：" + initSize);
					// console.log("压缩后：" + ndata.length);
					// console.log("ndata:" + ndata);

					// console.log(
					// 	"压缩率：" + ~~((100 * (initSize - ndata.length)) / initSize) + "%"
					// );
					tCanvas.width = tCanvas.height = canvas.width = canvas.height = 0;

					document.getElementById("com_before").innerHTML = '压缩前：' + initSize
					document.getElementById("com_after").innerHTML = '压缩后：' + ndata.length
					document.getElementById("com_ratio").innerHTML = '压缩率：' + parseInt(((100 * (initSize - ndata.length)) / initSize)) +
						"%"

					return ndata;
				}

			}
		</script>
	</body>
</html>
